// 2014年版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

// go:构建linux | | | freebsd | | |蜻蜓| | solaris
// +构建linux freebsd dragonfly solaris

package rand

import (
	"internal/syscall/unix"
)

// maxGetRandomRead依赖于平台。
func init() {
	altGetRandom = batched(getRandomBatch, maxGetRandomRead)
}

// batched返回一个函数，该函数通过分块调用f来填充[]字节
// 进入最多为readMax字节的子片。
func batched(f func([]byte) bool, readMax int) func([]byte) bool {
	return func(buf []byte) bool {
		for len(buf) > readMax {
			if !f(buf[:readMax]) {
				return false
			}
			buf = buf[readMax:]
		}
		return len(buf) == 0 || f(buf)
	}
}

// 如果内核太旧，无法支持getrandom syscall（），
// unix.GetRandom将立即返回ENOSYS，然后我们将返回到
// 正在读取rand_unix.go中的/dev/uradom。unix.GetRandom缓存ENOSYS
// 因此，在这种情况下，我们只会遭受一次系统调用开销。
// 如果内核支持getrandom（）系统调用，unix.getrandom将阻止
// 直到内核具有足够的随机性（因为我们不使用GRND_非块）。
// 在这种情况下，unix.GetRandom不会返回错误。
func getRandomBatch(p []byte) (ok bool) {
	n, err := unix.GetRandom(p, 0)
	return n == len(p) && err == nil
}
